This code is modified from the original OPUSreader2 documentation vignettes/opusreader2_introduction.Rmd by Philip Baumann and Thomas Knecht. It reads OPUS binary files and extracts metadata and absorbance data, which can then be plotted.
The main function, read_opus(), reads one or more OPUS
files and returns a nested list of class list_opusreader2.
Each list contains both the spectral data and metadata for each file.
The dsn argument is the data source name. It can be a
character vector of folder paths (to read files recursively) or specific
OPUS file paths. Start by testing the read_opus function on your
corrected spectra folder, and saving the output of the first file.
#load opusreader2 from github.com/spectral-cockpit
library(opusreader2)
#save the path to your corrected spectra
# # Mac path
# corr_spectra <- "/Users/adrianneseiden/Library/CloudStorage/Box-Box/Salk Institute Project/AKS Salk files/Adrianne_FTIRdata/Corrected_files" # nolint
# # Windows path
# corr_spectra <- "C:/Users/adria/Box/Box-Box/Salk Institute Project/AKS Salk files/Adrianne_FTIRdata/Corrected_files" # nolint
# # Relative path
# corr_spectra <- "../Adrianne_FTIRdata/Corrected_files"
#save the data from your corrected files as 'data_test'
data_test <- read_opus(dsn = corr_spectra)
#check the names of the list
names(data_test)
> [1] "DRIFTS_pot001_13Cwheat_wk0_root_250725_corr.0"
> [2] "DRIFTS_pot030_13Csoy_wk10_root_250725_corr.0"
> [3] "DRIFTS_pot032_13Cwheat_wk0_root_250725_corr.0"
> [4] "DRIFTS_pot047_13Crice_wk0_root_250725_corr.0"
> [5] "DRIFTS_pot053_13Cwheat_wk10_root_250725_corr.0"
> [6] "DRIFTS_pot055_13Crice_wk10_root_250725_corr.0"
> [7] "DRIFTS_pot055qmark_13Crice_wk10_root_250725_corr.0"
> [8] "DRIFTS_pot062_13Csoy_wk0_root_250725_corr.0"
> [9] "DRIFTS_pot079_13Crice_wk0_root_250725_corr.0"
> [10] "DRIFTS_pot080_13Csoy_wk10_root_250725_corr.0"
> [11] "DRIFTS_pot094_13Csoy_wk10_root_250725_corr.0"
> [12] "DRIFTS_pot094_13Csoy_wk10_soil_250630_corr.0"
> [13] "DRIFTS_pot103_13Crice_wk0_root_recNMR_250725_corr.0"
> [14] "DRIFTS_pot103_13Crice_wk0_root_vial1_250725_corr.0"
> [15] "DRIFTS_pot103_13Crice_wk0_root_vial2_250725_corr.0"
> [16] "DRIFTS_pot103_13Crice_wk0_root_vial3_250725_corr.0"
> [17] "DRIFTS_pot107_12Crice_wk0_root_really13_250725_corr.0"
# define 'meas_1' as the first element of the 'data_test' list
meas_1 <- data_test[[1]]Next I defined a function, plotSpectrum, to plot the spectral data from a single sample (meas_1)
# data is a list containing OPUS file data, including absorbance and metadata.
plotSpectrum <- function(data) { # nolint: object_name_linter.
ab_data <- data$ab
if (!is.null(ab_data) &&
!is.null(ab_data$wavenumbers) && !is.null(ab_data$data) &&
is.numeric(ab_data$wavenumbers) && is.numeric(ab_data$data) &&
length(ab_data$wavenumbers) == length(ab_data$data) &&
all(is.finite(ab_data$wavenumbers)) && all(is.finite(ab_data$data))) {
plot(
ab_data$wavenumbers, ab_data$data, type = "l",
xlab = "Wavenumber (cm⁻¹)", ylab = "Absorbance",
main = data$basic_metadata$dsn_filename,
xlim = rev(range(ab_data$wavenumbers))
)
} else {
cat("Absorbance data not found or not valid in this file.\n")
str(ab_data)
}
}
plotSpectrum(meas_1)I then defined the metadataTable function, to extract and display the a subset of the metadata stored in the data extracted by ‘read_opus’ in a table format.
To view all the available data categories, run ‘names(meas_1)’ in the console. To view the parameters within these categories use str(meas_1$category_name) where ‘category_name’ is ‘basic_metadata’, ‘optics’, etc.
The plotMetadata function combines the plot and table for a single spectrum.
plotMetadata <- function(data) { # nolint: object_name_linter.
plotSpectrum(data)
metadataTable(data)
}
plotMetadata(meas_1)| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot001_13Cwheat_wk0_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:18:39 GMT-7 |
| Max Y | 0.799607157707214 |
| Min Y | -0.0012896629050374 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56884765625 |
| Experiment (method) | SALK_soils_method.xpm |
The following for loop runs plotMetadata on each spectrum in the data_test list, which contains all the spectra in the folder. It will plot each spectrum and print its metadata below.
for (i in seq_along(data_test)) {
cat("#### Spectrum", i, ":", names(data_test)[i], "\n\n")
data_i <- data_test[[i]]
ab_data <- data_i$ab
valid <- !is.null(ab_data) &&
!is.null(ab_data$wavenumbers) && !is.null(ab_data$data) &&
is.numeric(ab_data$wavenumbers) && is.numeric(ab_data$data) &&
length(ab_data$wavenumbers) == length(ab_data$data) &&
all(is.finite(ab_data$wavenumbers)) && all(is.finite(ab_data$data))
if (valid) {
plotSpectrum(data_i)
print(metadataTable(data_i))
} else {
cat("Data not valid or missing for this spectrum.\n")
str(ab_data)
}
}| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot001_13Cwheat_wk0_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:18:39 GMT-7 |
| Max Y | 0.799607157707214 |
| Min Y | -0.0012896629050374 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56884765625 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot030_13Csoy_wk10_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:21:37 GMT-7 |
| Max Y | 0.84355878829956 |
| Min Y | -0.00326710939407349 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56689453125 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot032_13Cwheat_wk0_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:22:45 GMT-7 |
| Max Y | 0.909599244594574 |
| Min Y | -0.00415003532543778 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56982421875 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot047_13Crice_wk0_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:23:56 GMT-7 |
| Max Y | 0.712926685810089 |
| Min Y | -0.00133463030215353 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56591796875 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot053_13Cwheat_wk10_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:24:39 GMT-7 |
| Max Y | 0.997280716896057 |
| Min Y | -0.00962971057742834 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56591796875 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot055_13Crice_wk10_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:26:35 GMT-7 |
| Max Y | 0.816974341869354 |
| Min Y | -0.00123318459372967 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56689453125 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot055qmark_13Crice_wk10_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:25:51 GMT-7 |
| Max Y | 0.907369911670685 |
| Min Y | -0.00234174402430654 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56591796875 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot062_13Csoy_wk0_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:27:28 GMT-7 |
| Max Y | 0.687717080116272 |
| Min Y | -0.00538174575194716 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56884765625 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot079_13Crice_wk0_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:28:00 GMT-7 |
| Max Y | 0.816869914531708 |
| Min Y | -0.00257659493945539 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56787109375 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot080_13Csoy_wk10_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:28:56 GMT-7 |
| Max Y | 0.77625048160553 |
| Min Y | -0.00814440380781889 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56689453125 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot094_13Csoy_wk10_root_250725_corr.0 |
| Timestamp | 2025-07-25 20:29:09 GMT-7 |
| Max Y | 1.27848649024963 |
| Min Y | -0.00875786785036325 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56689453125 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot094_13Csoy_wk10_soil_250630_corr.0 |
| Timestamp | 2025-07-25 20:46:03 GMT-7 |
| Max Y | 0.821687042713165 |
| Min Y | -0.00153941253665835 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.454833984375 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot103_13Crice_wk0_root_recNMR_250725_corr.0 |
| Timestamp | 2025-07-25 20:30:32 GMT-7 |
| Max Y | 0.836920917034149 |
| Min Y | -0.00138377456460148 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56982421875 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot103_13Crice_wk0_root_vial1_250725_corr.0 |
| Timestamp | 2025-07-25 20:30:55 GMT-7 |
| Max Y | 0.826825261116028 |
| Min Y | -0.000596170837525278 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56787109375 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot103_13Crice_wk0_root_vial2_250725_corr.0 |
| Timestamp | 2025-07-25 20:31:26 GMT-7 |
| Max Y | 0.984898567199707 |
| Min Y | -0.00565983727574348 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56591796875 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot103_13Crice_wk0_root_vial3_250725_corr.0 |
| Timestamp | 2025-07-25 20:31:46 GMT-7 |
| Max Y | 0.983739078044891 |
| Min Y | -0.0026757272426039 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56591796875 |
| Experiment (method) | SALK_soils_method.xpm |
| Parameter | Value |
|---|---|
| File Name | DRIFTS_pot107_12Crice_wk0_root_really13_250725_corr.0 |
| Timestamp | 2025-07-25 20:32:00 GMT-7 |
| Max Y | 1.03206670284271 |
| Min Y | -0.00172662467230111 |
| Aperture Setting | 6 mm |
| Scanner Velocity | 10.0S |
| Result Spectrum | AB |
| Resolution | 4 |
| Sample Scans | 400 |
| End Frequency | 400 |
| Start Frequency | 4000 |
| Duration | 364.56591796875 |
| Experiment (method) | SALK_soils_method.xpm |
This code looks for files with the same sample number and stacks their spectra, to check whether reruns are consistent.
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
echo = TRUE,
results = "markup",
include = TRUE
)
library(opusreader2)
library(RColorBrewer)
#save the path to your corrected spectra
# # Mac path
# corr_spectra <- "/Users/adrianneseiden/Library/CloudStorage/Box-Box/Salk Institute Project/AKS Salk files/Adrianne_FTIRdata/Corrected_files" # nolint
# # Windows path
# corr_spectra <- "C:/Users/adria/Box/Box-Box/Salk Institute Project/AKS Salk files/Adrianne_FTIRdata/Corrected_files" # nolint
# Relative path
# corr_spectra <- "../Adrianne_FTIRdata/Corrected_files"
data_test <- read_opus(dsn = corr_spectra)
# Helper to extract sample number from filename (e.g., "pot094")
extract_sample_number <- function(filename) {
m <- regexpr("[a-z]{3}[0-9]+", filename)
if (m[1] != -1) {
regmatches(filename, m)
} else {
NA
}
}
# Helper to extract sample type (e.g.,"soil", "root")
extract_sample_type <- function(filename) {
m <- regexpr("soil|root", filename, ignore.case = TRUE)
if (m[1] != -1) {
tolower(regmatches(filename, m))
} else {
NA
}
}
# Group files by sample number & sample type
sample_numbers <- sapply(names(data_test), extract_sample_number)
sample_types <- sapply(names(data_test), extract_sample_type)
# Create unique combinations of sample number and sample type
sample_combinations <- paste(sample_numbers, sample_types, sep = "_")
unique_combinations <- unique(sample_combinations[!is.na(sample_numbers)
& !is.na(sample_types)])
# Plot stacked spectra for each unique combination
library(RColorBrewer)
for (combination in unique_combinations) {
idx <- which(sample_combinations == combination)
if (length(idx) > 1) {
# Extract sample number and type from combination
parts <- strsplit(combination, "_")[[1]]
sample_num <- parts[1]
sample_type <- parts[2]
spectra <- data_test[idx]
colors <- brewer.pal(min(length(spectra), 8), "Set1")
plot(NULL, xlim = rev(range(spectra[[1]]$ab$wavenumbers)),
ylim = range(sapply(spectra, function(x) x$ab$data), na.rm = TRUE),
xlab = "Wavenumber (cm⁻¹)", ylab = "Absorbance",
main = paste("Stacked spectra for", sample_num, "-", sample_type),
bty = "l")
for (i in seq_along(spectra)) {
ab_data <- spectra[[i]]$ab
if (!is.null(ab_data) && !is.null(ab_data$wavenumbers) &&
!is.null(ab_data$data)) {
lines(ab_data$wavenumbers, ab_data$data, col = colors[i], lwd = 2)
}
}
legend("topright",
inset = c(-0.05, -0.02),
legend = names(spectra),
col = colors[seq_along(spectra)],
lwd = 2,
xpd = TRUE,
bty = "n")
}
}This code stacks spectra of the same crop and timepoint.
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
echo = TRUE,
results = "markup",
include = TRUE
)
# Helper functions to extract crop and timepoint from filename
extract_crop <- function(filename) {
m <- regexpr("rice|wheat|soy", filename, ignore.case = TRUE)
if (m[1] != -1) tolower(regmatches(filename, m)) else NA
}
extract_time <- function(filename) {
m <- regexpr("wk[0-9]+", filename, ignore.case = TRUE)
if (m[1] != -1) tolower(regmatches(filename, m)) else NA
}
# Get crop and time for each file
crops <- sapply(names(data_test), extract_crop)
times <- sapply(names(data_test), extract_time)
# Unique crop-time combinations
combos <- na.omit(unique(paste(crops, times, sep = "_")))
library(RColorBrewer)
for (combo in combos) {
idx <- which(paste(crops, times, sep = "_") == combo)
if (length(idx) > 1) {
spectra <- data_test[idx]
colors <- brewer.pal(min(length(spectra), 8), "Set1")
plot(NULL, xlim = rev(range(spectra[[1]]$ab$wavenumbers)),
ylim = range(sapply(spectra, function(x) x$ab$data), na.rm = TRUE),
xlab = "Wavenumber (cm⁻¹)", ylab = "Absorbance",
main = paste("Stacked spectra for", combo),
bty = "l")
for (i in seq_along(spectra)) {
ab_data <- spectra[[i]]$ab
if (!is.null(ab_data) &&
!is.null(ab_data$wavenumbers)
&& !is.null(ab_data$data)) {
lines(ab_data$wavenumbers, ab_data$data, col = colors[i], lwd = 2)
}
}
legend("topright",
inset = c(-0.05, -0.02),
legend = names(spectra),
col = colors[seq_along(spectra)],
lwd = 2,
xpd = TRUE,
bty = "n")
}
}This code is modified from code by Stephany Soledad Chacon, “Box> Salk Institute Project> Salk Data> FTIR_Intact_decomposition_pots> FTIR_analysis.Rmd”. Using data in the DPT format, we can extrapolate sample attributes from the file names, then normalize and visualize spectra across replicates, crops, and timepoints. The width of the line bounding the spectra represents the range of the data.
#> Files found in directory:
#> [1] "DRIFTS_KBr250630_400scans1.0.dpt"
#> [2] "DRIFTS_pot001_13Cwheat_wk0_root_250725.0.dpt"
#> [3] "DRIFTS_pot030_13Csoy_wk10_root_250725.0.dpt"
#> [4] "DRIFTS_pot032_13Cwheat_wk0_root_250725.0.dpt"
#> [5] "DRIFTS_pot047_13Crice_wk0_root_250725.0.dpt"
#> [6] "DRIFTS_pot053_13Cwheat_wk10_root_250725.0.dpt"
#> [7] "DRIFTS_pot055_13Crice_wk10_root_250725.0.dpt"
#> [8] "DRIFTS_pot055_13Crice_wk10_root_qmark_250725.0.dpt"
#> [9] "DRIFTS_pot062_13Csoy_wk0_root_250725.0.dpt"
#> [10] "DRIFTS_pot079_13Crice_wk0_root_250725.0.dpt"
#> [11] "DRIFTS_pot080_13Csoy_wk10_root_250725.0.dpt"
#> [12] "DRIFTS_pot094_13Csoy_wk10_root_250725.0.dpt"
#> [13] "DRIFTS_pot094_13Csoy_wk10_soil_250630.0.dpt"
#> [14] "DRIFTS_pot103_13Crice_wk0_root_recNMR_250725.0.dpt"
#> [15] "DRIFTS_pot103_13Crice_wk0_root_vial1_250725.0.dpt"
#> [16] "DRIFTS_pot103_13Crice_wk0_root_vial2_250725.2.dpt"
#> [17] "DRIFTS_pot103_13Crice_wk0_root_vial3_250725.0.dpt"
#> [18] "DRIFTS_pot107_12Crice_wk0_root_really13_250725.0.dpt"
#> Number of .dpt files: 18
Using the long format dataframe dpt_data format
example: DRIFTS_pot094_13Csoy_wk10_soil_250630.0.dpt
#> Column filenames: wavenumber absorbance filename
#> [1] "pot"
#> [1] "001" "030" "032" "047" "053" "055" "062" "079" "080" "094" "103" "107"
#> [1] 13 12
#> [1] "wheat" "soy" "rice"
#> [1] "wk0" "wk10"
#> [1] "root" "soil"
#> [1] "250725" "250630"
#> [1] NA "qmark" "recNMR" "vial1" "vial2" "vial3" "really13"
#> # A tibble: 6 × 11
#> wavenumber absorbance filename source ID isotope crop timepoint type
#> <dbl> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr> <chr>
#> 1 3998. 0.0115 DRIFTS_pot00… pot 001 13 wheat wk0 root
#> 2 3997. 0.0115 DRIFTS_pot00… pot 001 13 wheat wk0 root
#> 3 3995. 0.0115 DRIFTS_pot00… pot 001 13 wheat wk0 root
#> 4 3994. 0.0115 DRIFTS_pot00… pot 001 13 wheat wk0 root
#> 5 3993. 0.0115 DRIFTS_pot00… pot 001 13 wheat wk0 root
#> 6 3991. 0.0115 DRIFTS_pot00… pot 001 13 wheat wk0 root
#> # ℹ 2 more variables: run_date <chr>, notes <chr>
FALSE [1] "001" "032" "062" "079" "103" "107"
#> [1] "030" "053" "055" "080" "094"
#> [1] "094"
#> [1] "001" "032" "053"
#> [1] "055" "079" "103" "107"
#> [1] "030" "062" "080" "094"